package com.huahua.api.util;

import cn.hutool.core.lang.Opt;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.google.common.collect.Maps;
import com.huahua.api.entity.dto.mofang.FormRecordListDto;
import com.huahua.api.entity.dto.mofang.LoginDto;
import com.huahua.api.entity.dto.mofang.UserInfoDto;
import org.jsoup.Connection;
import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.jsoup.nodes.Element;
import org.jsoup.nodes.Node;
import org.jsoup.select.Elements;

import java.io.IOException;
import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * @author LoveHuahua
 * @date 2022年02月14日 22:56
 * @description believe in yourself
 */
public class MoFangUtil {
    /**
     * 通过这个地址获取扫码登录的状态
     */
    private static final String checkLoginUrl = "http://login.b8n.cn/qr/weixin/student/8?op=checklogin";

    /**
     * 通过这个地址获取用户
     */
    private static final String preGetLogin = "http://xgmf.g8n.cn/student";


    private static final String signRecordUrl = "http://xgmf.g8n.cn/student/course/";

    private static final String formRecDetailUrl = "http://xgmf.g8n.cn/student/course/";


    private static final ObjectMapper OBJECT_MAPPER = new ObjectMapper();
    private final static Pattern COMPILE = Pattern.compile("(?<=var qrurl = \\\").*(?=\\\")");
    private final static Pattern getFormRecDetailRegex = Pattern.compile("(?<=iniFormData = ).*(})");


    public static String getSignRecordUrl(Integer courseId, Integer formId) {
        return signRecordUrl + courseId + "/profiles/" + formId + "?op=getlist";
    }

    /**
     * 获取表单记录url
     *
     * @param formId 表单id
     * @param recId  记录id
     * @return
     */
    public static String getFormRecDetailUrl(Integer coureId, Integer formId, Integer recId) {
        return formRecDetailUrl + coureId + "/profiles/" + formId + "?id=" + recId;
    }

    /**
     * 获取表单记录url
     *
     * @param formId 表单id
     * @return
     */
    public static String getInputFormUrl(Integer coureId, Integer formId) {
        return formRecDetailUrl + coureId + "/profiles/" + formId;
    }


    public static LoginDto getLoginUrl() {
        Document document = null;
        LoginDto loginDto = new LoginDto();
        try {
            Connection.Response preResponse = Jsoup.connect(preGetLogin).followRedirects(true).execute();
            Map<String, String> cookies = preResponse.cookies();
            Connection.Response execute = Jsoup.connect("http://login.b8n.cn/qr/weixin/student/8").cookies(cookies).execute();
            cookies.put("s", execute.cookie("s"));

            String cookie = OBJECT_MAPPER.writeValueAsString(cookies);
            loginDto.setCookie(cookie);
            document = execute.parse();
        } catch (IOException e) {
            e.printStackTrace();
        }

        String text = document.body().toString();
        Matcher matcher = COMPILE.matcher(text);
        if (matcher.find()) {
            String group = matcher.group();
            loginDto.setLoginUrl(group);
        }
        return loginDto;
    }


    /**
     * 获取个人信息
     *
     * @param cookie
     */
    public static List<UserInfoDto> getUserInfo(String cookie) {
        List<UserInfoDto> userInfoDtos = new ArrayList<>();
        try {
            HashMap<String, String> map = OBJECT_MAPPER.readValue(cookie, new TypeReference<HashMap<String, String>>() {
            });

            Document checkLoginResponse = Jsoup.connect(checkLoginUrl).cookies(map).ignoreContentType(true).ignoreHttpErrors(true).get();
            String text = checkLoginResponse.text();
            JsonNode jsonNode = OBJECT_MAPPER.readValue(text, JsonNode.class);
            boolean loginSuccess = jsonNode.get("status").asBoolean();
            if (loginSuccess) {
                //获取扫码回调
                String url = jsonNode.get("url").asText();
                System.out.println(url);
                Connection.Response response = Jsoup.connect(url).followRedirects(true).ignoreHttpErrors(false).ignoreContentType(true).cookies(map).header("Referer", "http://login.b8n.cn/").execute();
                Map<String, String> cookies = response.cookies();
                map.putAll(cookies);

                Document home = response.parse();
                System.out.println(home);

                for (Element element : home.select("#mainarea > div.card.mb-3.course")) {
                    Elements courseElement = element.select("div > a");
                    UserInfoDto userInfoDto = new UserInfoDto();
                    userInfoDto.setDeptName(courseElement.select(" div > h5").text());
                    userInfoDto.setCourseUrl(courseElement.attr("href"));
                    userInfoDto.setCookie(OBJECT_MAPPER.writeValueAsString(map));
                    List<Node> p = courseElement.select("p").first().childNodes();
                    if (p.size() == 2) {
                        userInfoDto.setCourseName(p.get(1).toString());
                    }
                    userInfoDtos.add(userInfoDto);
                }
            }

        } catch (IOException e) {
            e.printStackTrace();
        }
        return userInfoDtos;
    }

    /**
     * 获取签到记录
     *
     * @return
     */
    public static List<FormRecordListDto> getSignRecord(HashMap<String, String> cookie, Integer courseId, Integer formId) {
        String signRecordUrl = getSignRecordUrl(courseId, formId);
        List<FormRecordListDto> formRecordListDtos = null;
        try {
            Document document = Jsoup.connect(signRecordUrl).cookies(cookie).ignoreContentType(true).ignoreHttpErrors(true).get();
            String text = document.body().text();
            formRecordListDtos = OBJECT_MAPPER.readValue(text, new TypeReference<List<FormRecordListDto>>() {
            });
        } catch (IOException e) {
            e.printStackTrace();
        }
        return Opt.ofNullable(formRecordListDtos).orElseGet(ArrayList::new);
    }

    /**
     * 获取历史表单的信息
     *
     * @return
     */
    public static HashMap<String, String> getFormRecDetail(HashMap<String, String> cookie, Integer courseId, Integer formId, Integer recId) {


        String formRecDetailUrl = getFormRecDetailUrl(courseId, formId, recId);
        Document document = null;
        try {
            document = Jsoup.connect(formRecDetailUrl).cookies(cookie).get();
            //未知字段 反正有用
            String form_id = document.select("#profileform > input[name=form_id]").attr("value");
            //未知字段 反正有用
            String formid = document.select("#profileform > input[name=formid]").attr("value");

            Matcher matcher = getFormRecDetailRegex.matcher(document.toString());
            if (matcher.find()) {
                String group = matcher.group();
                JsonNode jsonNode = OBJECT_MAPPER.readValue(group, JsonNode.class);
                Iterator<Map.Entry<String, JsonNode>> fields = jsonNode.fields();
                HashMap<String, String> map = Maps.newHashMap();
                while (fields.hasNext()) {
                    Map.Entry<String, JsonNode> next = fields.next();
                    String key = next.getKey();
                    String s = next.getValue().asText();
                    map.put("formdata["+key + "]", s);
                }
                map.put("form_id", form_id);
                map.put("formid", formid);
                return map;
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
        return Maps.newHashMap();
    }

    public static String submitForm(HashMap<String, String> cookie, HashMap<String, String> map, Integer courseId, Integer formId) {
        String inputFormUrl = getInputFormUrl(courseId, formId);

        try {
            Document post = Jsoup.connect(inputFormUrl).followRedirects(true).cookies(cookie).data(map).postDataCharset("UTF-8").ignoreHttpErrors(true).ignoreContentType(true).post();
            return post.toString();
        } catch (IOException e) {
            e.printStackTrace();
        }
        return "系统错误 请手动打卡";
    }


}
